using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Storage;
using Microsoft.Xna.Framework.Content;

namespace GameEngine.Cameras
{
    /// <summary>
    /// A camera that contains its matrices, position, viewport, etc...
    /// </summary>
    public class GECamera
    {
        private Vector3 position = new Vector3(0, 0, 0);
        private Vector3 target = new Vector3(0, 0, 0);
        private Vector3 upVector = Vector3.Up;

        private double hRotation = 0;
        private double vRotation = 0;
        private double zoomTarget = 1;
        private double zoomValue = 1;

        private Matrix world;
        private Matrix view;
        private Matrix projection;
        private Viewport viewport;

        public Matrix World { get { return world; } }
        public Matrix View { get { return view; } }
        public Matrix Projection { get { return projection; } }
        public Viewport Viewport { get { return viewport; } }
        public Vector3 Position { get { return position; } }

        /// <summary>
        /// Initializes a GECamera
        /// </summary>
        /// <param name="viewPort">The viewport to bind it to</param>
        public GECamera(Viewport viewPort)
        {
            SetViewport(viewPort);
        }

        public void SetViewport(Viewport viewPort)
        {
            viewport = viewPort;

            viewport.MinDepth = 1f;
            viewport.MaxDepth = 100000f;
        }

        public void Update()
        {
            if (zoomTarget > zoomValue)
            {
                if (zoomTarget - zoomValue < 4)
                    zoomValue = zoomTarget;
                else
                    zoomValue += 4;
            }

            else if (zoomTarget < zoomValue)
            {
                if (zoomTarget - zoomValue > -4)
                    zoomValue = zoomTarget;
                else
                    zoomValue -= 4;
            }

            world = Matrix.Identity;

            view = Matrix.CreateLookAt(position, target, upVector);

            projection = Matrix.CreatePerspectiveFieldOfView(MathHelper.Pi / 3.0f, (float)viewport.Width / (float)viewport.Height, viewport.MinDepth, viewport.MaxDepth);
        }

        public void UpadateCamera()
        {
            hRotation = hRotation > Math.PI * 2 ? hRotation - Math.PI * 2 : hRotation;
            hRotation = hRotation < 0 ? hRotation + Math.PI * 2 : hRotation;

            vRotation = vRotation > Math.PI * 2 ? vRotation - Math.PI * 2 : vRotation;
            vRotation = vRotation < 0 ? vRotation + Math.PI * 2 : vRotation;

            upVector = vRotation > Math.PI / 2 && vRotation < Math.PI / 2 * 3 ? new Vector3(0, -1, 0) : new Vector3(0, 1, 0);

            position.X = (float)(zoomValue * Math.Cos(vRotation) * Math.Cos(hRotation));
            position.Y = (float)(zoomValue * Math.Sin(vRotation));
            position.Z = (float)(zoomValue * Math.Cos(vRotation) * Math.Sin(hRotation));
        }

        public void MoveInOrbit(double horizontalRotation, double verticalRotation)
        {
            hRotation += horizontalRotation;
            vRotation += verticalRotation;

            UpadateCamera();
        }

        public void Zoom(double newZoomValue)
        {
            zoomTarget += newZoomValue;

            UpadateCamera();
        }

    }
}
